package de.gbeine.java.ebookmanager.yaml;

import java.util.HashSet;
import java.util.Set;

import org.yaml.snakeyaml.nodes.MappingNode;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.nodes.NodeTuple;
import org.yaml.snakeyaml.nodes.ScalarNode;
import org.yaml.snakeyaml.nodes.SequenceNode;

/**
 *
 */
public class DataFetcher {

    /**
     * Extract a string value from a node using a NodeSelector.
     *
     * Iterates through all tags of a node and return the value of the first tag
     * that is matched by the NodeSelector.
     *
     * @param map The node to fetch a value from
     * @param pNodeSelector The selector to apply on the node
     * @return The node's matching tag's value
     */
    public static String fetchValue(final MappingNode map, final NodeSelector pNodeSelector) {
        String tagValue = null;
        for (final NodeTuple tuple : map.getValue()) {
            if (pNodeSelector.select(tuple.getKeyNode())) {
            	tagValue = ((ScalarNode) tuple.getValueNode()).getValue();
                break;
            }
        }
        if (null == tagValue) {
            throw new IllegalArgumentException(map + " does not contain a value for node selector");
        }
        return tagValue;
    }

    /**
     * Extract a sub nodes from a node using a NodeSelector.
     *
     * Iterates through all sub nodes of a node and add it to the result set
     * if the sub node is matched by the NodeSelector.
     *
     * @param map The map to fetch nodes from
     * @param pNodeSelector The selector to apply on sub nodes
     * @return The set of sub nodes selected
     */
    public static Set<Node> fetchNodes(final MappingNode map, final NodeSelector pNodeSelector) {
        final Set<Node> childs = new HashSet<Node>();
        for (final NodeTuple tuple : map.getValue()) {
            if (pNodeSelector.select(tuple.getKeyNode())) {
                final SequenceNode seqNode = (SequenceNode) tuple.getValueNode();
                for (final Node seqElement : seqNode.getValue()) {
                    childs.add(seqElement);
                }
            }
        }
        return childs;
    }

}
